# module name trie.py
# $Id: trie.py ddcad87fab9c 2013/08/17 19:20:30 pgurumur $
# Copyright (c) 2013 Prabhu Gurumurthy <pgurumur@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# File trie.py generated on Sat, August 17, 2013 02:07:46 AM
#
__version__  = "$Revision: ddcad87fab9c $"
__author__   = "$Author: pgurumur $"
__modified__ = "$Date: 2013-08-17 19:20:30Z $"

import exception, stdlib, ip

def check_object(function):
   def wrapper(*args, **kwargs):
      arguments = []
      obj = args[1]
      value = None
      if isinstance(obj, str):
         value = Node(obj)
      elif isinstance(obj, Node):
         value = obj

      arguments.append(args[0])
      arguments.append(value)
      return function(*arguments, **kwargs)
   return wrapper

class Node(object):
   def __init__(self, Address = None):
      self._ip = None
      self._parent = None
      self._children = []

      if Address:
         try:
            self._ip = ip.ip(Address)
         except exception.IPError as err:
            raise exception.TrieError(err)

   def __str__(self):
      return str(self._ip)

   def __int__(self):
      return int(self._ip)

   def __len__(self):
      return len(self._ip)

   def __contains__(self, Object):
      retval = False
      if isinstance(Object, Node):

      return Object.ip in self.ip

   def childip(self, Object):

   @check_object
   def __iadd__(self, Object):
      if Object in self and not Object in self.children:
         self._children.append(Object)
         Object.parent = self
      else:
         raise exception.TrieError(
               "cannot remove invalid child subnet %s" %str(Object))

      return self

   @check_object
   def __isub__(self, Object):
      if Object in self and Object in self.children:
         self._children.remove(Object)
      else:
         raise exception.TrieError(
               "cannot remove invalid child subnet %s" %str(Object))

      return self

   def get_parent(self):
      return self._parent

   def set_parent(self, Object):
      if isinstance(Object, Node):
         self._parent = Object
      else:
         raise exception.TrieError("invalid parent object")

   parent = property(get_parent, set_parent)
   ip = property(fget = lambda self: self._ip)
   children = property(fget = lambda self: self._children)
